import subprocess
import sys
import logging
import os
import tempfile
import json
from intelhex import IntelHex

# 启用调试日志
logging.basicConfig(level=logging.DEBUG)

# 配置文件路径
CONFIG_FILE = "rolling_code_config.json"

# 默认配置
DEFAULT_CONFIG = {
    'rolling_code': 1,
    'code_address': '0x8005800',  # 使用字符串形式的十六进制
    'code_size': 1,  # 字节数
    'hex_file': 'build/firmware.hex'  # 添加hex文件路径
}

def load_config():
    """从配置文件加载配置，如果不存在则创建"""
    try:
        if os.path.exists(CONFIG_FILE):
            with open(CONFIG_FILE, 'r') as f:
                config = json.load(f)
                # 确保所有必要的配置项都存在
                merged_config = {**DEFAULT_CONFIG, **config}
                # 将地址转换为整数
                if isinstance(merged_config['code_address'], str):
                    merged_config['code_address'] = int(merged_config['code_address'], 16)
                return merged_config
        else:
            # 配置文件不存在，创建默认配置
            print(f"配置文件 {CONFIG_FILE} 不存在，创建默认配置...")
            config = DEFAULT_CONFIG.copy()
            save_config(config)
            # 返回默认配置（地址已经是字符串格式）
            config['code_address'] = int(config['code_address'], 16)
            return config
    except Exception as e:
        print(f"读取配置文件出错: {str(e)}")
        print("使用默认配置...")
        config = DEFAULT_CONFIG.copy()
        config['code_address'] = int(config['code_address'], 16)
        return config

def save_config(config):
    """保存配置到文件"""
    try:
        # 将地址转换为十六进制字符串
        save_config = config.copy()
        
        # 如果地址是整数，转换为十六进制字符串
        if isinstance(config['code_address'], int):
            save_config['code_address'] = f"0x{config['code_address']:X}"
        # 如果已经是字符串，直接使用
        elif isinstance(config['code_address'], str):
            save_config['code_address'] = config['code_address']
            
        with open(CONFIG_FILE, 'w') as f:
            json.dump(save_config, f, indent=4)
    except Exception as e:
        print(f"保存配置文件出错: {str(e)}")

def increment_rolling_code(hex_file):
    """增加滚码值并返回新的hex文件路径"""
    try:
        # 读取配置
        config = load_config()
        current_code = config['rolling_code']
        code_address = config['code_address']
        
        # 读取原始hex文件
        ih = IntelHex(hex_file)
            

        # 写入新的滚码值（2字节）
        for i in range(config['code_size']):
            ih[code_address + i] = (current_code >> (i * 8)) & 0xFF
        
        # 增加滚码值
        new_code = (current_code + 1) & 0xFFFF  # 使用0xFFFF作为2字节掩码
        if new_code == 0:  # 防止溢出回到0
            new_code = 1
        print(f"当前滚码值: {current_code} -> 新滚码值: {new_code}")
        
        # 更新并保存配置
        config['rolling_code'] = new_code
        save_config(config)
        # 创建临时文件保存修改后的hex
        temp_dir = tempfile.gettempdir()
        temp_hex = os.path.join(temp_dir, "temp.hex")
        ih.write_hex_file(temp_hex)
        
        return temp_hex
        
    except Exception as e:
        print(f"修改滚码时出错: {str(e)}")
        return None

def flash_hex(hex_file):
    try:
        print("开始下载固件...")
        # 构建 pyocd 命令
        cmd = [
            "pyocd", "flash",
            "--erase=chip",
            "--target", "n32g430c8l7",
            hex_file
        ]
        
        # 执行命令并实时输出结果
        process = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True
        )
        
        # 实时打印输出
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                break
            if output:
                print(output.strip())
        
        # 获取返回码
        return_code = process.poll()
        
        if return_code == 0:
            print("固件下载完成！")
        else:
            print(f"下载失败，返回码: {return_code}")
            
    except Exception as e:
        print(f"下载过程中出现错误: {str(e)}")
        return False
    
    return return_code == 0

def main():
    # 从配置文件读取hex文件路径
    config = load_config()
    original_hex = config['hex_file']
    
    try:
        # 修改滚码
        temp_hex = increment_rolling_code(original_hex)
        if not temp_hex:
            print("滚码修改失败！")
            return False
            
        # 下载修改后的固件
        success = flash_hex(temp_hex)
        
        # 清理临时文件
        try:
            os.remove(temp_hex)
        except:
            pass
            
        return success
        
    except Exception as e:
        print(f"程序执行出错: {str(e)}")
        return False

if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)